1
//--------------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // File: SerialTaskQueue.cs
7 //--------------------------------------------------------------------------
9 using System
.Collections
.Generic
;
10 using System
.Diagnostics
;
12 namespace System
.Threading
.Tasks
14 /// <summary>Represents a queue of tasks to be started and executed serially.</summary>
15 public class SerialTaskQueue
17 /// <summary>The ordered queue of tasks to be executed. Also serves as a lock protecting all shared state.</summary>
18 private Queue
<object> _tasks
= new Queue
<object>();
19 /// <summary>The task currently executing, or null if there is none.</summary>
20 private Task _taskInFlight
;
22 /// <summary>Enqueues the task to be processed serially and in order.</summary>
23 /// <param name="taskGenerator">The function that generates a non-started task.</param>
24 public void Enqueue(Func
<Task
> taskGenerator
) { EnqueueInternal(taskGenerator); }
26 /// <summary>Enqueues the non-started task to be processed serially and in order.</summary>
27 /// <param name="task">The task.</param>
28 public Task
Enqueue(Task task
) { EnqueueInternal(task); return task; }
30 /// <summary>Gets a Task that represents the completion of all previously queued tasks.</summary>
31 public Task
Completed() { return Enqueue(new Task(() => { }
)); }
33 /// <summary>Enqueues the task to be processed serially and in order.</summary>
34 /// <param name="taskOrFunction">The task or functino that generates a task.</param>
35 /// <remarks>The task must not be started and must only be started by this instance.</remarks>
36 private void EnqueueInternal(object taskOrFunction
)
39 if (taskOrFunction
== null) throw new ArgumentNullException("task");
42 // If there is currently no task in flight, we'll start this one
43 if (_taskInFlight
== null) StartTask_CallUnderLock(taskOrFunction
);
44 // Otherwise, just queue the task to be started later
45 else _tasks
.Enqueue(taskOrFunction
);
49 /// <summary>Called when a Task completes to potentially start the next in the queue.</summary>
50 /// <param name="ignored">The task that completed.</param>
51 private void OnTaskCompletion(Task ignored
)
55 // The task completed, so nothing is currently in flight.
56 // If there are any tasks in the queue, start the next one.
58 if (_tasks
.Count
> 0) StartTask_CallUnderLock(_tasks
.Dequeue());
62 /// <summary>Starts the provided task (or function that returns a task).</summary>
63 /// <param name="nextItem">The next task or function that returns a task.</param>
64 private void StartTask_CallUnderLock(object nextItem
)
66 Task next
= nextItem
as Task
;
67 if (next
== null) next
= ((Func
<Task
>)nextItem
)();
69 if (next
.Status
== TaskStatus
.Created
) next
.Start();
71 next
.ContinueWith(OnTaskCompletion
);